package services

import (
	"CampusRecruitment/pkg/consts"
	"CampusRecruitment/pkg/models"
	"CampusRecruitment/pkg/types"
	"CampusRecruitment/pkg/types/errors"
	"CampusRecruitment/pkg/types/resps"
	"fmt"
	"gorm.io/gorm"
	"strings"
)

func CreateJob(db *gorm.DB, form *types.CreateJobForm) (*models.Job, error) {
	job := models.Job{
		JobName:     form.JobName,
		PublishId:   form.PublishId,
		CompId:      form.CompId,
		MinWage:     form.MinWage,
		MaxWage:     form.MaxWage,
		WageSection: SelectWageSection(form.MinWage),
		JobNum:      form.JobNum,
		Desc:        form.Desc,
		City:        form.City,
		Address:     form.Address,
		Tags:        ChangeArrayToString(form.Tags),
	}
	if err := db.Model(&models.Job{}).Create(&job).Error; err != nil {
		return nil, errors.AutoDbErr(err)
	}
	return GetJobById(db, job.Id)

}

func QueryJobs(db *gorm.DB, q string) *gorm.DB {
	return db.Model(&models.Job{}).Where("job_name LIKE ?", "%"+q+"%").Order("created_at")
}

func UpdateJobById(db *gorm.DB, form *types.UpdateJobForm) (*models.Job, error) {
	updateForm := models.Job{}
	if form.City != "" {
		updateForm.City = form.City
	}
	if form.MinWage != 0 {
		updateForm.MinWage = form.MinWage
	}
	if form.MaxWage != 0 {
		updateForm.MaxWage = form.MaxWage
	}
	if form.Address != "" {
		updateForm.Address = form.Address
	}
	if form.Desc != "" {
		updateForm.Desc = form.Desc
	}
	if form.JobName != "" {
		updateForm.JobName = form.JobName
	}
	if form.JobNum != "" {
		updateForm.JobNum = form.JobNum
	}
	if len(form.Tags) != 0 {
		updateForm.Tags = ChangeArrayToString(form.Tags)
	}
	updateForm.WageSection = SelectWageSection(form.MinWage)
	if err := db.Debug().Model(&models.Job{}).Where("id", form.Id).Updates(&updateForm).Error; err != nil {
		return nil, errors.AutoDbErr(err)
	}
	return GetJobById(db, form.Id)
}

func SearchJobsWithCond(db *gorm.DB, cond *types.JobCondForm) *gorm.DB {
	return db.Table(models.Job{}.TableName()).Where("state", "active").Where(cond)
}

func GetJobsIdByCompId(db *gorm.DB, id models.Id) ([]models.Id, error) {
	ids := make([]models.Id, 0)
	if err := db.Model(&models.Job{}).Where("comp_id", id).Select("id").Scan(&ids).Error; err != nil {
		return nil, errors.AutoDbErr(err)
	}
	return ids, nil
}

func GetJobById(db *gorm.DB, id models.Id) (*models.Job, error) {
	job := models.Job{}
	if err := db.Model(&models.Job{}).Where("id", id).First(&job).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.ErrUserNotFound
		}
		return nil, errors.AutoDbErr(err)
	}
	return &job, nil
}

func DeleteJob(db *gorm.DB, id models.Id) error {
	job := models.Job{}
	if err := db.Model(&models.Job{}).Where("id", id).Delete(&job).Error; err != nil {
		return errors.AutoDbErr(err)
	}
	return nil
}

func CloseJobByPublishId(db *gorm.DB, id models.Id) error {
	return db.Model(&models.Job{}).Where("publish_id", id).Update("state", "inactive").Error
}

func CLoseJob(db *gorm.DB, id models.Id) error {
	ids := make([]models.Id, 1)
	ids[0] = id
	if err := UpdateJobsState(db, ids, "inactive"); err != nil {
		return err
	}
	return nil
}

func UpdateJobsState(db *gorm.DB, ids []models.Id, state string) error {
	if err := db.Model(&models.Job{}).Where("id IN ?", ids).Update("state", state).Error; err != nil {
		return errors.AutoDbErr(err)
	}
	return nil
}

func SelectWageSection(minWage int) string {
	if minWage <= 3000 {
		return consts.WageA
	}
	if minWage <= 5000 && minWage > 3000 {
		return consts.WageB
	}
	if minWage <= 10000 && minWage > 5000 {
		return consts.WageC
	}
	if minWage <= 15000 && minWage > 10000 {
		return consts.WageD
	}
	if minWage <= 20000 && minWage > 15000 {
		return consts.WageE
	}
	if minWage > 20000 {
		return consts.WageF
	}
	return consts.Wage0
}

func ChangeArrayToString(arrays []string) string {
	str := strings.Join(arrays, ",")
	return str
}

func ChangeStringToArray(str string) []string {
	arr := strings.Split(str, ",")
	return arr
}

func GetHotJobsByCompId(db *gorm.DB, compId models.Id) ([]resps.HotJobResp, error) {
	hotJobs := make([]resps.HotJobResp, 0)
	if err := db.Model(&models.Job{}).Where("state", "active").Where("comp_id", compId).Order("updated_at").Limit(6).Scan(&hotJobs).Error; err != nil {
		return nil, errors.AutoDbErr(err)
	}
	return hotJobs, nil
}

func GetJobNumByCompId(db *gorm.DB, compId models.Id) int {
	var num int
	db.Model(&models.Job{}).Raw("SELECT COUNT(1) FROM t_job WHERE comp_id = ? AND state = 'active';", compId).Scan(&num)
	return num
}

func GetJobList(db *gorm.DB, form *types.GetJobListForm) (*resps.GetJobLists, error) {
	JobList := make([]resps.GetJobListResp, 0)
	sql := "SELECT * FROM (SELECT tj.id as job_id,tj.comp_id,tj.publish_id,tj.job_name,tj.city as job_city,tj.wage_section,tj.min_wage,tj.max_wage,tj.job_num,tj.tags,tc.comp_name,tc.comp_type,tc.people_num as comp_people,tc.logo,tu.`name` as username,tu.position FROM t_job as tj INNER JOIN t_comp as tc ON tj.comp_id = tc.id INNER JOIN t_user as tu ON tj.publish_id = tu.id where tj.state = 'active') as resp where 1=1"
	if form.City != "" {
		sql = sql + " and resp.job_city = '" + form.City + "'"
	}
	if form.CompType != "" {
		sql = sql + " and resp.comp_type = '" + form.CompType + "'"
	}
	if form.CompPeople != "" {
		sql = sql + " and resp.comp_people = '" + form.CompPeople + "'"
	}
	if form.WageSection != "" {
		sql = sql + " and resp.wage_section = '" + form.WageSection + "'"
	}
	if form.Q != "" {
		sql = sql + " and resp.job_name like '%" + form.Q + "%'" + " or resp.comp_name like '%" + form.Q + "%'"
	}

	res := make([]resps.GetJobListResp, 0)
	db.Raw(sql + ";").Scan(&res)
	count := len(res)
	sql = sql + " limit " + fmt.Sprint((form.Page()-1)*form.PageSize()) + "," + fmt.Sprint(form.Page()*form.PageSize()) + ";"
	if err := db.Raw(sql).Scan(&JobList).Error; err != nil {
		return nil, errors.AutoDbErr(err)
	}
	resp := resps.GetJobLists{
		JobList:  JobList,
		Total:    count,
		Page:     form.Page(),
		PageSize: form.PageSize(),
	}
	return &resp, nil
}

func GetJobCity(db *gorm.DB) ([]string, error) {
	var citys []string
	if err := db.Raw("SELECT DISTINCT city from t_job;").Scan(&citys).Error; err != nil {
		return nil, errors.AutoDbErr(err)
	}
	return citys, nil
}

func GetJobSendState(db *gorm.DB, userId, jobId models.Id) (*models.Send, error) {
	send := models.Send{}
	if err := db.Model(&models.Send{}).Where("user_id", userId).
		Where("job_id", jobId).First(&send).Error; err != nil {
		if errors.IsNotFoundErr(err) {
			return nil, nil
		}
		return nil, errors.AutoDbErr(err)
	}
	return &send, nil
}

func SaveSend(db *gorm.DB, sendId models.Id, form *types.CreateSendForm) error {
	return db.Model(&models.Send{}).Where(sendId).Updates(&form).Error
}

func CreateSend(db *gorm.DB, form *types.CreateSendForm) error {
	send := models.Send{
		Path:     form.Path,
		Username: form.Username,
		JobName:  form.JobName,
		JobId:    form.JobId,
		CompId:   form.CompId,
		UserId:   form.UserId,
		Filename: form.Filename,
	}
	return db.Model(&models.Send{}).Create(&send).Error
}

func GetJobSend(db *gorm.DB, compId models.Id) *gorm.DB {
	return db.Model(&models.Send{}).Where("comp_id", compId).Order("updated_at")
}
